﻿#r "..\\..\\Sitecore.CodeGenerator.Scripty\\bin\\Debug\\Sitecore.Codegenerator.Scripty.dll"
#r "..\\..\\Lib\\Sitecore.Kernel.DLL"
#r "..\\..\\packages\\BoC.Glass.Mapper.Sc.1.0.3\\lib\\net45\\Glass.Mapper.Sc.dll"
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Editing;
using Sitecore.Codegenerator.Scripty;
using static Sitecore.Codegenerator.Scripty.CodeGenerationExtensions;
using System.Linq;
using global::Glass.Mapper.Sc.Fields;

var templates = SerializedDataUtil.GetTemplates(Project);
foreach (var template in templates)
{
    string extends;
    if (template.BaseTemplates.Any())
    {
        extends = string.Concat(" : ", string.Join(", ", template.BaseTemplates.Select(b => string.Concat("I", b.SyncItem.Name.Identifier()))));
    }
    else
    {
        extends = string.Empty; //" : IModelBase";
    }

    var templateFile = Output[string.Concat("I", template.SyncItem.Name.Identifier(), ".gen.cs")];

    templateFile.WriteLine("// <autogenerated>");
    templateFile.WriteLine("//   This file was generated by Sitecore.CodeGenerator.Scripty");
    templateFile.WriteLine("//   Any changes made to this file manually will be lost next time the file is regenerated.");
    templateFile.WriteLine("//   Please ensure that this file is not checked in to your source control system, as it should be regenerated during a build and we want to avoid merge issues.");
    templateFile.WriteLine("// </autogenerated>");

    templateFile.WriteLine($"namespace {Project.Analysis.AssemblyName}.Models");
    templateFile.WriteLine("{");
    templateFile.WriteLine("    using System;");
    templateFile.WriteLine("    using System.Collections.Generic;");
    templateFile.WriteLine("    using System.Collections.Specialized;");
    templateFile.WriteLine("    using global::Glass.Mapper.Sc.Configuration;");
    templateFile.WriteLine("    using global::Glass.Mapper.Sc.Configuration.Attributes;");
    templateFile.WriteLine("    using global::Glass.Mapper.Sc.Fields;");
    templateFile.WriteLine("");
    templateFile.WriteLine("    /// <summary>");
    templateFile.WriteLine($"    /// Represents a mapped type for item {template.SyncItem.ID} in Sitecore.");
    templateFile.WriteLine($"    /// Path: {template.SyncItem.ItemPath}");
    templateFile.WriteLine("    /// </summary>");
    templateFile.WriteLine($"    [SitecoreType(TemplateId = \"{template.SyncItem.ID}\")]");
    templateFile.WriteLine($"    public partial interface I{template.SyncItem.Name.Identifier()}{extends}");
    templateFile.WriteLine("    {");

    foreach (var section in template.Sections)
    {
        templateFile.WriteLine($"        #region {section.SyncItem.Name}");
        templateFile.WriteLine("");
        foreach (var field in section.Fields)
        {
            var fieldId = field.SyncItem.ID;
            var fieldOptions = GetFieldOptions(field.FieldTypeName, fieldId);
            
            // Add custom options, like setting the return type of a field property explicitly

            // Dog -> Food
            if ("{1033D7C1-9C1A-4C65-8316-81B6D5E46EB5}".Equals(fieldId))
            {
                fieldOptions.GlassFieldTypeName = "IEnumerable<IFood>";
            }

            // Dog -> Dog's friends
            if ("{20D7789D-BCE0-473E-BB46-59B216CE2C10}".Equals(fieldId))
            {
                fieldOptions.GlassFieldTypeName = "IEnumerable<IDog>";
                fieldOptions.AttributeExtras = ", Setting = SitecoreFieldSettings.DontLoadLazily";
            }

            if (!string.IsNullOrWhiteSpace(field.FieldTitle))
            {
                templateFile.WriteLine("        /// <summary>");
                templateFile.WriteLine($"        /// {field.FieldTitle}");
                templateFile.WriteLine("        /// </summary>");
            }

            templateFile.WriteLine($"        [SitecoreField(FieldId = \"{field.SyncItem.ID}\"{fieldOptions.AttributeExtras ?? string.Empty })]");
            templateFile.WriteLine($"        {fieldOptions.GlassFieldTypeName} {field.SyncItem.Name.Identifier()} {{ get; set; }}");
        }

        templateFile.WriteLine("");
        templateFile.WriteLine("        #endregion");
        templateFile.WriteLine("");
    }

    templateFile.WriteLine("    }");
    templateFile.WriteLine("}");
}

public class FieldOptions
{
    public string GlassFieldTypeName { get; set; }
    public string AttributeExtras { get; set; }
}

public FieldOptions GetFieldOptions(string fieldType, string fieldId)
{
    FieldOptions result = new FieldOptions();
    switch (fieldType)
    {
        case "Checkbox":
            result.GlassFieldTypeName = "bool";
            break;
        case "Integer":
            result.GlassFieldTypeName = "int";
            break;
        case "Number":
            result.GlassFieldTypeName = typeof(Decimal).Name;
            break;
        case "Date":
        case "Datetime":
            result.GlassFieldTypeName = typeof(DateTime).Name;
            break;
        case "File":
        case "File Drop Area":
            result.GlassFieldTypeName = typeof(File).Name;
            break;
        case "Name Value List":
        case "Name Lookup Value List":
            result.GlassFieldTypeName = typeof(System.Collections.Specialized.NameValueCollection).Name;
            break;
        // case "???": result.GlassFieldTypeName = typeof(HtmlEncodedString).Name; break;
        case "Image":
            result.GlassFieldTypeName = typeof(Image).Name;
            break;
        case "Droplink":
        case "Droptree":
        case "General Link":
        case "General Link with Search":
        case "Version Link":
        case "link":
            result.GlassFieldTypeName = typeof(Link).Name;
            break;
        // case "???": result.GlassFieldTypeName = typeof(LinkType).Name; break;
        case "Tristate":
            result.GlassFieldTypeName = typeof(TriState).Name;
            break;
        default:
            result.GlassFieldTypeName = "string";
            break;
    }

    return result;
}